"""
Name  : Levi
Email : lvze@tedu.cn
Time  : 2022-5-6
Env   : Python3.6

聊天室 ： udp网络套接字和进程的综合训练使用网络循环模型
"""
from socket import *
from multiprocessing import Process

# 服务器地址
ADDR = ("0.0.0.0",8889)

# 存用户信息 {name:address}
user = {}

# 处理进入聊天室
def do_login(sock,name,addr):
    if name in user or "管理" in name:
        sock.sendto(b'FAIL',addr)
    else:
        sock.sendto(b'OK', addr)
        #循环通知其他人
        msg = "欢迎 %s 加入群聊"%name
        for key,address in user.items():
            sock.sendto(msg.encode(),address)
        user[name] = addr # 字典中增加一项
    # print(user) # 测试

#　处理用户聊天信息
def do_chat(sock,name,content):
    msg = "%s : %s"%(name,content)
    for key, address in user.items():
        # 不等于本人就发送
        if name != key:
            sock.sendto(msg.encode(), address)

#　处理退出
def do_quit(sock,name):
    del user[name] # 删除用户
    msg = "%s 退出了群聊"%name
    for key, address in user.items():
        sock.sendto(msg.encode(), address)

#　子进程函数负责处理客户端请求
def handle(sock):
    # 循环接收客户端请求，分情况讨论处理
    while True:
        request, addr = sock.recvfrom(1024)
        tmp = request.decode().split(' ', 2)  # 简单解析
        if tmp[0] == "LOGIN":
            do_login(sock, tmp[1], addr)  # tmp -> [LOGIN,name]
        elif tmp[0] == "CHAT":
            do_chat(sock, tmp[1], tmp[2])  # ｔｍｐ->[CHAT,name,content]
        elif tmp[0] == "QUIT":
            do_quit(sock, tmp[1])  # tmp -> [QUIT,name]


# 入口函数 ： 搭建网络模型
def main():
    # udp套接字
    sock = socket(AF_INET,SOCK_DGRAM)
    sock.bind(ADDR)
    #　创建子进程
    p = Process(target=handle,args=(sock,))
    p.start()
    # 发送管理员消息
    while True:
        content = input("管理员消息:")
        msg = "CHAT 管理员消息 " + content
        sock.sendto(msg.encode(),ADDR) # 父进程－》子


if __name__ == '__main__':
    main()